#!/usr/bin/env python

# A news ticker for GNOME
# Written by V.G.
# Free for modification and redistribution
# Report bugs to vgramanathan@gmail.com

import os
import sys
import gtk
import sexy
import socket
import gobject
import urllib2
import feedparser
import gnomeapplet
import ConfigParser

http_proxy   = ""
feed_uri     = "http://news.google.com/?output=atom"
timeout      = 3 # Connection timeout in seconds
refresh_time = 30 # Refresh every 30 minutes

show_news    = "firefox %s &" # Command to use for opening links, %s is the url

scroll_speed = 40 # Number of pixels per second that the scroller moves
ticker_width = 300
hpadding     = 2
vpadding     = 1
back_color   = "white"
separator    = "+++" # String that separates two titles

config = ConfigParser.SafeConfigParser()
print os.path.expanduser('~/.gpanelticker')
if len(config.read([os.path.expanduser('~/.gpanelticker')]))>0:
    if config.has_option("connection","http_proxy"):
        http_proxy=config.get("connection","http_proxy")
    if config.has_option("connection","feed_uri"):
        feed_uri=config.get("connection","feed_uri")
    if config.has_option("connection","timeout"):
        timeout=config.getint("connection","timeout")
    if config.has_option("connection","refresh_time"):
        refresh_time=config.getint("connection","refresh_time")
    if config.has_option("appearance","scroll_speed"):
        scroll_speed=config.getint("appearance","scroll_speed")
    if config.has_option("appearance","back_color"):
        back_color=config.get("appearance","back_color")
    if config.has_option("appearance","back_color"):
        hpadding=config.getint("appearance","hpadding")
    if config.has_option("appearance","hpadding"):
        vpadding=config.getint("appearance","vpadding")
    if config.has_option("appearance","vpadding"):
        ticker_width=config.getint("appearance","ticker_width")
    if config.has_option("appearance","ticker_width"):
        ticker_width=config.getint("appearance","ticker_width")
    if config.has_option("appearance","separator"):
        separator=config.get("appearance","separator")
    if config.has_option("misc","show_news"):
        show_news=config.get("misc","show_news")

print scroll_speed

def scroll(obj):
    obj.left=obj.left-1
    if(obj.left<=-obj.width):
        obj.left=ticker_width
    obj.container.move(obj.scroller,obj.left,0)
    obj.applet.show_all()
    return True

def openitem(widget,event,url):
    if event.button==1:
        command=show_news.replace("%s",url)
        os.system(command)

def newsupdate(obj):
    socket.setdefaulttimeout(timeout)
    proxy=urllib2.ProxyHandler({"http":http_proxy})
    if http_proxy=="":
        try:
            data=feedparser.parse(feed_uri)
        except (urllib2.URLError,urllib2.HTTPError), e:
            data=None
    else:
        try:
            data=feedparser.parse(feed_uri, handlers=[proxy])
        except (urllib2.URLError,urllib2.HTTPError), e:
            data=None
    if obj==None:
        return data
    obj.feeddata=data
    return True

class NewsTicker:
    def __init__(self,applet,iid):
        self.feeddata=newsupdate(None)
        self.left=ticker_width
        self.width=0
        self.applet=applet;
        self.applet.set_size_request(ticker_width,-1)
        self.align=gtk.Alignment()
        self.align.set_padding(vpadding,vpadding,hpadding,hpadding)
        self.dummybox=gtk.EventBox()
        self.eventbox=gtk.EventBox()
        self.dummybox.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse(back_color))
        self.eventbox.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse(back_color))
        self.frame=gtk.Frame()
        self.frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        self.frame.set_size_request(ticker_width,-1)
        self.container=gtk.Fixed()
        self.scroller=gtk.HBox()
        self.container.put(self.scroller,0,0)
        self.eventbox.add(self.container)
        self.align.add(self.eventbox)
        self.frame.add(self.align)
        self.dummybox.add(self.frame)
        self.applet.add(self.dummybox)
        self.applet.connect("destroy",self.destroy)
        if self.feeddata==None:
            p=gtk.Label()
            p.set_text("(EE) Could not retrieve feed data")
            p.set_justify(gtk.JUSTIFY_CENTER)
            self.scroller.add(p)
        elif len(self.feeddata.entries)==0:
            p=gtk.Label()
            p.set_text("(EE) Feed not read or empty")
            p.set_justify(gtk.JUSTIFY_CENTER)
            self.scroller.add(p)
        else:
            for s in self.feeddata.entries:
                p=sexy.UrlLabel()
                s.link.replace("?","\?")
                p.set_markup("  "+separator+"  <a href=\""+s.link+"\">"+s.title+"</a>")
                p.connect("button-press-event",openitem,s.link)
                self.scroller.add(p)
                self.width+=p.size_request()[0]
            self.timer=gobject.timeout_add(1000/scroll_speed,scroll,self)
        self.update=gobject.timeout_add(refresh_time*60*1000,newsupdate,self)
        self.applet.show_all()
    def destroy(self,applet):
        applet.hide()
        gtk.main_quit()

def exec_factory(applet,iid):
    NewsTicker(applet,iid)
    return gtk.TRUE

if len(sys.argv)>=2 and sys.argv[1]=="run":
    window=gtk.Window(gtk.WINDOW_TOPLEVEL)
    applet=gnomeapplet.Applet()
    window.connect("destroy",gtk.main_quit)
    exec_factory(applet,None)
    applet.reparent(window)
    window.show_all()
    gtk.main()
else:
    gnomeapplet.bonobo_factory("OAFIID:GNOME_GPanelTickerApplet_Factory",gnomeapplet.Applet.__gtype__,"A panel ticker for GNOME","0",exec_factory)
